package com.pajk.user.api.dubbo;

import java.util.Date;
import java.util.List;
import java.util.Random;

import net.pocrd.core.ServiceException;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.Assert;
import org.testng.Reporter;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.pajk.commons.types.VersionedValue;
import com.pajk.user.api.UserService;
import com.pajk.user.dal.index.Index;
import com.pajk.user.dal.model.UserDO;
import com.pajk.user.exception.UserServiceException;
import com.pajk.user.model.User;
import com.pajk.user.model.UserRelation;
import com.pajk.user.model.enums.BloodType;
import com.pajk.user.model.enums.CertificationType;
import com.pajk.user.model.enums.ChannelType;
import com.pajk.user.model.enums.Gender;
import com.pajk.user.model.enums.RelationType;
import com.pajk.user.model.enums.Role;

public class UserServiceIT
{
  private UserService userService = null;
  private ClassPathXmlApplicationContext appContext = null;
  private static final String TestOpenId = "testAddCredit1abc";

  @BeforeClass
  public void setup()
  {
    this.appContext = new ClassPathXmlApplicationContext("classpath:META-INF/spring/user-service-consumer.xml");
    this.appContext.start();
    this.userService = ((UserService)this.appContext.getBean("userService"));
  }
  @AfterClass
  public void teardown() { this.appContext.close();
  }

  @Test
  public void getOrCreateUserByOpenIdTest()
  {
    User user = this.userService.getOrCreateUserByOpenId(TestOpenId, ChannelType.WEIXIN);
    Assert.assertNotNull(user);
    System.out.println(user.getId());
  }

  @Test(dependsOnMethods={"getOrCreateUserByOpenIdTest"})
  public void getUserByOpenIdTest()
  {
    User user1 = this.userService.getUserByOpenId(TestOpenId, ChannelType.WEIXIN);
    Assert.assertNotNull(user1);
  }

  @Test(expectedExceptions={IllegalArgumentException.class})
  public void getUserByOpenId_openIdNullTest()
  {
    String openId = null;
    this.userService.getUserByOpenId(openId, ChannelType.WEIXIN);
  }

  @Test(expectedExceptions={IllegalArgumentException.class})
  public void getUserByOpenId_notWeixinChannelTest()
  {
    String openId = "xxx";
    this.userService.getUserByOpenId(openId, ChannelType.INVALID_CHANNEL);
  }

  @Test
  public void getUserByOpenId_openIdNotExistTest()
  {
    String openId = "thisisanotexistopenidaccount";
    User user = this.userService.getUserByOpenId(openId, ChannelType.WEIXIN);
    Assert.assertNull(user);
  }

  @Test(dependsOnMethods={"getOrCreateUserByOpenIdTest", "getUserByOpenIdTest"})
  public void getUserByIdTest()
  {
    User user1 = this.userService.getUserByOpenId(TestOpenId, ChannelType.WEIXIN);
    User user2 = this.userService.getUserById(user1.getId());
    Assert.assertNotNull(user2);
  }

  @Test
  public void getUserById_NotExistTest()
  {
    User user2 = this.userService.getUserById(Long.valueOf(0L));
    Assert.assertNull(user2);
  }

  //@Test(dataProvider = "excel", dataProviderClass = ExcelDataProvider.class)
  //参数:Map<String,String> datadriven
  //取值:datadriven.get("key")
  @Test
  public void updateUserInfoTest()
  {
    User u1 = this.userService.getOrCreateUserByOpenId(TestOpenId, ChannelType.WEIXIN);
    Long userId = u1.getId();

    java.sql.Date birthday = new java.sql.Date(1114876800000L);
    BloodType bloodType = BloodType.A;
    String certId = "510104198009144111";
    CertificationType certType = CertificationType.MILITARY;
    Integer height = Integer.valueOf(175);
    Integer weight = Integer.valueOf(70000);
    String passwd = "fake-password123";
    String physique = "fakephysique123";
    Role role = Role.INVALID_ROLE;
    String wanliId = "fake-wanliid123";
    String yizhangId = "fake-yizhangid123";
    Long mobile = getRandomMobile();
    
//    UserStatus userStatus = UserStatus.INVALID;//现在是不会设置这个的，故去掉
//    Integer wanliCredits = Integer.valueOf(11);//现在是不会设置这个的，故去掉
//    Integer credits = Integer.valueOf(111);//现在是不会设置这个的，故去掉

    UserDO userDO = new UserDO();
    userDO.setMobile(mobile);
    userDO.setBirthday(birthday);
    userDO.setBloodType(bloodType);
    userDO.setCertId(certId);
    userDO.setCertType(certType);
    userDO.setHeight(height);
    userDO.setWeight(Integer.valueOf(70000));
    userDO.setPassword(passwd);
    userDO.setPhysique(physique);
    userDO.setRole(role);
    userDO.setWanliId(wanliId);
    userDO.setYizhangId(yizhangId);
    this.userService.updateUserInfo(userId, userDO);

    User u2 = this.userService.getUserById(userId);
    Assert.assertEquals(u2.getBirthday().getTime(), birthday.getTime());
    Assert.assertEquals(u2.getBloodType(), bloodType);
    Assert.assertEquals(u2.getCertId(), certId);
    Assert.assertEquals(u2.getCertType(), certType);
    Assert.assertEquals(u2.getHeight(), height);
    Assert.assertEquals(u2.getWeight(), weight);
    Assert.assertEquals(u2.getPassword(), passwd);
    Assert.assertEquals(u2.getPhysique(), physique);
    Assert.assertEquals(u2.getRole(), role);
    Assert.assertEquals(u2.getYizhangId(), yizhangId);
    Assert.assertEquals(u2.getGmtCreate(), u1.getGmtCreate());
    Assert.assertEquals(u2.getMobile(), mobile);
  }

  @Test
  public void updateMobileTest()
  {
    User u1 = this.userService.getOrCreateUserByOpenId(TestOpenId, ChannelType.WEIXIN);
    Long userId = u1.getId();

    Long mobile = Long.valueOf(getRandomMobile());
    this.userService.updateMobile(userId, mobile);
    User user1 = this.userService.getUserById(userId);
    Assert.assertEquals(user1.getMobile(), mobile);

    User user2 = this.userService.getOrCreateUserByOpenId("testAddCredit1abc_hello", ChannelType.WEIXIN);
    Long userId2 = user2.getId();
    try {
      this.userService.updateMobile(userId2, mobile);
    } catch (UserServiceException e) {
      Assert.assertTrue(true);
    }
    
    
  }

  private long getRandomMobile() {
    long m = Math.round(Math.random() * 89999999 + 10000000);
    return Long.parseLong("130" + m);
  }

  
  /**
   * 快速创建关注用户
   * 为某用户创建人员并增加关注关系
   *
   * @param followerId 为此用户创建创建关注用户
   * @param followee 需要快速创建的被关注用户实体
   * @param followReason 关注类型，比如配偶、孩子等
   * @return 被关注用户id
   */
  @Test(dependsOnMethods={"getOrCreateUserByOpenIdTest"},description="由于微信2.0只传入4个参数，这里只构造这些数据(User) --对应sims.createMember接口")
  public void createFolloweeTest(){
		User user = this.userService.getOrCreateUserByOpenId(TestOpenId,
				ChannelType.WEIXIN);
		long followerId = user.getId();
		System.out.println(followerId);
		User followee = new User();// set哪些参数?
		Date d = new java.util.Date();
		Gender gender = Gender.MALE;
		String nick = "老豆";
		followee.setBirthday(d);
		followee.setGender(gender);//性别
		followee.setNick(nick);
		RelationType followReason = RelationType.FATHER;//sims:title字段
		String floweeNick = nick;
		long floweeId = this.userService.createFollowee(followerId, followee,
				followReason, floweeNick);
		System.out.println(floweeId);
		Reporter.log(String.valueOf(floweeId));
	    User user2 = this.userService.getUserById(floweeId);
	    Assert.assertNotNull(user2);
	    Assert.assertEquals(user2.getNick(), nick);
	    Assert.assertEquals(user2.getGender(), gender);
	    Assert.assertEquals(user2.getBirthday().getTime(), d.getTime());
	    //数据存user_relation表的检查?????
	    //待补充，校验UserRelation表的数据--现在没这个接口，需要从db或spring注入方式查询 --以后是否都这样做？太麻烦了
//	    Assert.assertEquals(user2.get), followReason);
	    
	    this.userService.cancelFollow(followerId, floweeId);
  }

  
  @Test(dependsOnMethods={"createFolloweeTest"},description="sims.deleteRelation")
  public void cancelFollowTest(){
		User user = this.userService.getOrCreateUserByOpenId(getRandomOpenId(),
				ChannelType.WEIXIN);
		long userId = user.getId();
		List<UserRelation> listUserRelation1 = this.userService.getFollowees(userId);
		//验证点1：新用户+初级评测，获取成员列表，检查-无家庭成员列表
		Assert.assertEquals(listUserRelation1.size(), 0);
		//验证点2：添加一个家人（父亲）+初级评测，获取成员列表，检查-获得成员列表中有一条记录（关系为父亲）
		long floweeIdForFather = createFollowee(userId,RelationType.FATHER);
		List<UserRelation> listUserRelation2 = this.userService.getFollowees(userId);
		Assert.assertEquals(listUserRelation2.size(), 1);
		//验证点3：删除一个家人（父亲），获取成员列表，检查-获得成员列表只有一条记录（关系为母亲）
		boolean cancelResult1 = this.userService.cancelFollow(userId, floweeIdForFather);
		Assert.assertTrue(cancelResult1);
		List<UserRelation> listUserRelation4 = this.userService.getFollowees(userId);
		Assert.assertEquals(listUserRelation4.size(), 0);
  }
  
  
  @Test(dependsOnMethods={"createFolloweeTest","cancelFollowTest"},description="sims.getUserFamilyRelations")
  public void getFolloweesTest(){
		User user = this.userService.getOrCreateUserByOpenId(getRandomOpenId(),
				ChannelType.WEIXIN);
		long userId = user.getId();
		List<UserRelation> listUserRelation1 = this.userService.getFollowees(userId);
		
		//验证点1：新用户+初级评测，获取成员列表，检查-无家庭成员列表
		Assert.assertEquals(listUserRelation1.size(), 0);
		//验证点2：添加一个家人（父亲）+初级评测，获取成员列表，检查-获得成员列表中有一条记录（关系为父亲）
		long floweeIdForFather = createFollowee(userId,RelationType.FATHER);
		List<UserRelation> listUserRelation2 = this.userService.getFollowees(userId);
		Assert.assertEquals(listUserRelation2.size(), 1);
		//验证点3：再次添加一个家人（母亲）+初级评测，获取成员列表，检查-获得成员列表中有两条记录（父亲和母亲）
		long floweeIdForMother = createFollowee(userId,RelationType.MOTHER);
		List<UserRelation> listUserRelation3 = this.userService.getFollowees(userId);
		Assert.assertEquals(listUserRelation3.size(), 2);
		//验证点4：删除一个家人（父亲），获取成员列表，检查-获得成员列表只有一条记录（关系为母亲）
		boolean cancelResult1 = this.userService.cancelFollow(userId, floweeIdForFather);
		Assert.assertTrue(cancelResult1);
		List<UserRelation> listUserRelation4 = this.userService.getFollowees(userId);
		Assert.assertEquals(listUserRelation4.size(), 1);
		//验证点5：再次删除一个家人（母亲），获取成员列表，检查-无家庭成员列表
		boolean cancelResult2 = this.userService.cancelFollow(userId, floweeIdForMother);
		Assert.assertTrue(cancelResult2);
		List<UserRelation> listUserRelation5 = this.userService.getFollowees(userId);
		Assert.assertEquals(listUserRelation5.size(), 0);
		
  }
  
  private long createFollowee(Long userId, RelationType followReason){
		User followee = new User();// set哪些参数?
		Date d = new Date();
		Gender gender = Gender.MALE;
		String nick = "老豆";
		followee.setBirthday(d);
		followee.setGender(gender);//性别
		followee.setNick(nick);
//		RelationType followReason = RelationType.FATHER;//sims:title字段
		String floweeNick = nick;
		long floweeId = this.userService.createFollowee(userId, followee,
				followReason, floweeNick);
		return floweeId;
  }
  
  private String getRandomOpenId(){
	  String openId = "testAddCredit" + new Random().nextInt();
	  return openId;
  }
  
  
  
  @Test
  public void updateUserRelationTest(){
		User user = this.userService.getOrCreateUserByOpenId(getRandomOpenId(),
				ChannelType.WEIXIN);
		long userId = user.getId();
		long floweeId = createFollowee(userId, RelationType.FATHER);

		Date birthday = new Date();
		Gender gender = Gender.FEMALE;
		User followee = new User(floweeId);
		followee.setBirthday(birthday);
		followee.setGender(gender);
		RelationType followReason = RelationType.SON;
		String floweeNick = "修改后的昵称";
		boolean updateResult = this.userService.updateUserRelation(userId, followee, followReason,
				floweeNick);
		Assert.assertTrue(updateResult);
		
	    User user2 = this.userService.getUserById(floweeId);
	    Assert.assertNotNull(user2);
	    Assert.assertEquals(user2.getNick(), floweeNick);
	    Assert.assertEquals(user2.getGender(), gender);
	    Assert.assertEquals(user2.getBirthday(), birthday);
		  //待补充，校验UserRelation表的数据--现在没这个接口，需要从db或spring注入方式查询
//	    Assert.assertEquals(), followReason);
  }
  
  

  @Test(description="")
  public void getUserExtDataTest(){
		User user = this.userService.getOrCreateUserByOpenId(getRandomOpenId(),
				ChannelType.WEIXIN);
		long userId = user.getId();
		String domain = "TEST";
		String extKey = "MULTIDBTX";
		String extData = "10";
		this.userService.setUserExtData(userId, domain, extKey, extData, null);
		VersionedValue<String> versionedValue = this.userService.getUserExtData(userId, domain, extKey);
		Assert.assertEquals(versionedValue.getValue(), extData);
  }
  
  @Test(description="万里通账号绑定：万里通ID长度大于32")
  public void bindWltAccount32Test(){
	  try{
		  this.userService.bindWltAccount(1l, "123456789012345678901234567890123");
		  Assert.fail();
	  }catch(RuntimeException e)
	  {
		  Assert.assertTrue(e.getMessage().contains("wanli id(123456789012345678901234567890123) too long!"));
	  }
  }
  
  @Test(description="万里通账号绑定：健康用户不存在")
  public void bindWltAccountNoUserTest(){	  
	  try{
		  this.userService.bindWltAccount(123l, "98920403");
		  Assert.fail();
	  }catch(RuntimeException e)
	  {
		  Assert.assertTrue(e.getMessage().contains("unknown error!"));
	  }
  }
  
  @Test(description="万里通账号绑定：健康用户存在,且之前已绑定万里通ID")
	public void bindWltAccountOldUserTest() {
	    // 初始化测试数据
		String openId = "testAddCredit" + new Random().nextInt();
		User user = this.userService.getOrCreateUserByOpenId(openId,
				ChannelType.WEIXIN);
		this.userService.updateMobile(user.getId(), new Random().nextLong());
		user = this.userService.getUserById(user.getId());
		
		// ID绑定
		this.userService.bindWltAccount(user.getId(), user.getWanliId());
		User currentUser= this.userService.getUserById(user.getId());
		// 验证绑定后，万里通ID
		Assert.assertEquals(user.getWanliId(), currentUser.getWanliId());
		
		// ID重新绑定
		this.userService.bindWltAccount(user.getId(), user.getWanliId()+"new");
		currentUser= this.userService.getUserById(user.getId());
		Assert.assertEquals(currentUser.getWanliId(), user.getWanliId()+"new");
	}
  
	@Test(description = "万里通账号绑定：健康用户存在,且之前未绑定过万里通ID")
	public void bindWltAccountFirstTest() {
		// 初始化测试数据
		String openId = "testAddCredit" + new Random().nextInt();
		User user = this.userService.getOrCreateUserByOpenId(openId,
				ChannelType.WEIXIN);

		// ID绑定
		this.userService.bindWltAccount(user.getId(), "98920403");
		User currentUser = this.userService.getUserById(user.getId());
		// 验证绑定后，万里通ID
		Assert.assertEquals("98920403", currentUser.getWanliId());
	}
  
//  @Test
//  public void TestException1() throws SQLException{
//	  SLog.info("这是一个异常的测试case1:抛Sql异常！");
//	  throw new SQLException("test sql exception!");
//  }
//  @Test
//  public void TestException2() throws SQLException{
//	  SLog.info("这是一个异常的测试case2:断言失败！");
//	  Assert.fail();
//  }
//  @Test
//  public void TestException3() throws SQLException{
//	  SLog.info("这是一个异常的测试case3:空指针！");
//	  List<String> ll = null;
//	  System.out.println(ll.size());
//  }
}